From 15ed35fcc779b847809d4cb2cde3b9d817e5be40 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 10 Mar 2008 11:08:11 -0600 Subject: [PATCH] [IA64] Prepare sioemu for SMP and save & restore. Use macros instead of constants. Signed-off-by: Tristan Gingold --- xen/arch/ia64/vmx/sioemu.c | 144 ++++++++++++++++++-------- xen/arch/ia64/vmx/vmx_fault.c | 8 +- xen/include/asm-ia64/sioemu.h | 3 +- xen/include/public/arch-ia64/sioemu.h | 36 +++++++ 4 files changed, 147 insertions(+), 44 deletions(-) diff --git a/xen/arch/ia64/vmx/sioemu.c b/xen/arch/ia64/vmx/sioemu.c index 7a533138af..fe6b740fd3 100644 --- a/xen/arch/ia64/vmx/sioemu.c +++ b/xen/arch/ia64/vmx/sioemu.c @@ -23,21 +23,14 @@ #include #include #include +#include +#include -static REGS * -sioemu_deliver (void) +static void +sioemu_save_regs (VCPU *vcpu) { - VCPU *vcpu = current; REGS *regs = vcpu_regs(vcpu); - unsigned long psr = vmx_vcpu_get_psr(vcpu); - - if (vcpu->vcpu_info->evtchn_upcall_mask) - panic_domain (NULL, "sioemu_deliver: aleady in stub mode\n"); - - /* All cleared, but keep BN. */ - vmx_vcpu_set_psr(vcpu, IA64_PSR_MC | (psr & IA64_PSR_BN)); - /* Save registers. */ vcpu->arch.arch_vmx.stub_saved[0] = regs->r16; vcpu->arch.arch_vmx.stub_saved[1] = regs->r17; vcpu->arch.arch_vmx.stub_saved[2] = regs->r18; @@ -56,13 +49,62 @@ sioemu_deliver (void) vcpu->arch.arch_vmx.stub_saved[15] = regs->r31; vcpu->arch.arch_vmx.stub_nats = (regs->eml_unat >> IA64_PT_REGS_R16_SLOT) & 0xffff; +} + +static void +sioemu_restore_regs (VCPU *vcpu) +{ + REGS *regs = vcpu_regs(vcpu); + + /* First restore registers. */ + regs->cr_iip = regs->r28; + regs->cr_ifs = regs->r30; + vmx_vcpu_set_psr (vcpu, regs->r29); + + regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT); + regs->eml_unat |= vcpu->arch.arch_vmx.stub_nats << IA64_PT_REGS_R16_SLOT; + + regs->r16 = vcpu->arch.arch_vmx.stub_saved[0]; + regs->r17 = vcpu->arch.arch_vmx.stub_saved[1]; + regs->r18 = vcpu->arch.arch_vmx.stub_saved[2]; + regs->r19 = vcpu->arch.arch_vmx.stub_saved[3]; + regs->r20 = vcpu->arch.arch_vmx.stub_saved[4]; + regs->r21 = vcpu->arch.arch_vmx.stub_saved[5]; + regs->r22 = vcpu->arch.arch_vmx.stub_saved[6]; + regs->r23 = vcpu->arch.arch_vmx.stub_saved[7]; + regs->r24 = vcpu->arch.arch_vmx.stub_saved[8]; + regs->r25 = vcpu->arch.arch_vmx.stub_saved[9]; + regs->r26 = vcpu->arch.arch_vmx.stub_saved[10]; + regs->r27 = vcpu->arch.arch_vmx.stub_saved[11]; + regs->r28 = vcpu->arch.arch_vmx.stub_saved[12]; + regs->r29 = vcpu->arch.arch_vmx.stub_saved[13]; + regs->r30 = vcpu->arch.arch_vmx.stub_saved[14]; + regs->r31 = vcpu->arch.arch_vmx.stub_saved[15]; + +} + +static REGS * +sioemu_deliver (void) +{ + VCPU *vcpu = current; + REGS *regs = vcpu_regs(vcpu); + unsigned long psr = vmx_vcpu_get_psr(vcpu); + + if (vcpu->vcpu_info->evtchn_upcall_mask) + panic_domain (NULL, "sioemu_deliver: aleady in stub mode\n"); + + /* All cleared, but keep BN. */ + vmx_vcpu_set_psr(vcpu, IA64_PSR_MC | (psr & IA64_PSR_BN)); + + /* Save registers. */ + sioemu_save_regs (vcpu); /* Context. */ regs->r28 = regs->cr_iip; regs->r29 = psr; regs->r30 = regs->cr_ifs; - regs->cr_ifs = 0; // pre-cover + regs->cr_ifs = 0; // pre-cover regs->cr_iip = vcpu->arch.event_callback_ip; regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT); @@ -90,33 +132,15 @@ sioemu_callback_return (void) u64 arg3 = regs->r21; if ((cmd & ~0x1UL) != 0) - panic_domain (NULL, - "sioemu_callback_return: bad operation (%lx)\n", cmd); + panic_domain (NULL, "sioemu_callback_return: bad operation (%lx)\n", + cmd); /* First restore registers. */ regs->cr_iip = regs->r28; regs->cr_ifs = regs->r30; vmx_vcpu_set_psr (vcpu, regs->r29); - regs->eml_unat &= ~(0xffffUL << IA64_PT_REGS_R16_SLOT); - regs->eml_unat |= vcpu->arch.arch_vmx.stub_nats << IA64_PT_REGS_R16_SLOT; - - regs->r16 = vcpu->arch.arch_vmx.stub_saved[0]; - regs->r17 = vcpu->arch.arch_vmx.stub_saved[1]; - regs->r18 = vcpu->arch.arch_vmx.stub_saved[2]; - regs->r19 = vcpu->arch.arch_vmx.stub_saved[3]; - regs->r20 = vcpu->arch.arch_vmx.stub_saved[4]; - regs->r21 = vcpu->arch.arch_vmx.stub_saved[5]; - regs->r22 = vcpu->arch.arch_vmx.stub_saved[6]; - regs->r23 = vcpu->arch.arch_vmx.stub_saved[7]; - regs->r24 = vcpu->arch.arch_vmx.stub_saved[8]; - regs->r25 = vcpu->arch.arch_vmx.stub_saved[9]; - regs->r26 = vcpu->arch.arch_vmx.stub_saved[10]; - regs->r27 = vcpu->arch.arch_vmx.stub_saved[11]; - regs->r28 = vcpu->arch.arch_vmx.stub_saved[12]; - regs->r29 = vcpu->arch.arch_vmx.stub_saved[13]; - regs->r30 = vcpu->arch.arch_vmx.stub_saved[14]; - regs->r31 = vcpu->arch.arch_vmx.stub_saved[15]; + sioemu_restore_regs (vcpu); /* Unmask events. */ vcpu->vcpu_info->evtchn_upcall_mask = 0; @@ -133,8 +157,7 @@ sioemu_deliver_event (void) REGS *regs; regs = sioemu_deliver (); - - regs->r16 = 0; + regs->r16 = SIOEMU_CB_EVENT; } void @@ -144,13 +167,32 @@ sioemu_io_emulate (unsigned long padr, unsigned long data, REGS *regs; regs = sioemu_deliver (); - regs->r16 = 1; + regs->r16 = SIOEMU_CB_IO_EMULATE; regs->r19 = padr; regs->r20 = data; regs->r21 = data1; regs->r22 = word; } +void +sioemu_wakeup_vcpu (int vcpu_id) +{ + REGS *regs; + + regs = sioemu_deliver(); + regs->r16 = SIOEMU_CB_WAKEUP_VCPU; + regs->r19 = vcpu_id; +} + +void +sioemu_sal_assist (struct vcpu *v) +{ + REGS *regs; + + regs = sioemu_deliver(); + regs->r16 = SIOEMU_CB_SAL_ASSIST; +} + static int sioemu_add_io_physmap (struct domain *d, unsigned long start, unsigned long size, unsigned long type) @@ -187,7 +229,7 @@ sioemu_hypercall (struct pt_regs *regs) // regs->r2, regs->r8, regs->r9); if (current->vcpu_info->evtchn_upcall_mask == 0) - panic_domain (NULL, "sioemu_hypercall: not in stub mode\n"); + panic_domain(NULL, "sioemu_hypercall: not in stub mode\n"); switch (regs->r2 & FW_HYPERCALL_NUM_MASK_LOW) { @@ -197,20 +239,40 @@ sioemu_hypercall (struct pt_regs *regs) break; case SIOEMU_HYPERCALL_START_FW: regs->cr_iip = regs->r8; - vmx_vcpu_set_psr (current, regs->r9); + vmx_vcpu_set_psr(current, regs->r9); current->vcpu_info->evtchn_upcall_mask = 0; break; case SIOEMU_HYPERCALL_ADD_IO_PHYSMAP: - regs->r8 = sioemu_add_io_physmap (current->domain, - regs->r8, regs->r9, regs->r10); + regs->r8 = sioemu_add_io_physmap(current->domain, + regs->r8, regs->r9, regs->r10); break; case SIOEMU_HYPERCALL_GET_TIME: { uint64_t sec, nsec; - get_wallclock (&sec, &nsec); + get_wallclock(&sec, &nsec); regs->r8 = (sec << 30) + nsec; break; } + case SIOEMU_HYPERCALL_GET_REGS: + sioemu_restore_regs(current); + break; + case SIOEMU_HYPERCALL_SET_REGS: + sioemu_save_regs(current); + break; + case SIOEMU_HYPERCALL_FLUSH_CACHE: + regs->r8 = ia64_sal_cache_flush(regs->r8); + break; + case SIOEMU_HYPERCALL_FREQ_BASE: + regs->r8 = ia64_sal_freq_base(regs->r8, ®s->r9, ®s->r10); + break; + case SIOEMU_HYPERCALL_DELIVER_INT: + regs->r8 = vlsapic_deliver_int(current->domain, + regs->r8, regs->r9, regs->r10); + break; + case SIOEMU_HYPERCALL_CALLBACK_RETURN: + regs->r2 = regs->r27; + sioemu_callback_return (); + break; default: panic_domain (NULL, "bad sioemu hypercall %lx\n", regs->r2); break; diff --git a/xen/arch/ia64/vmx/vmx_fault.c b/xen/arch/ia64/vmx/vmx_fault.c index 0ae63e16f2..f14372c466 100644 --- a/xen/arch/ia64/vmx/vmx_fault.c +++ b/xen/arch/ia64/vmx/vmx_fault.c @@ -208,8 +208,12 @@ vmx_ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long is vcpu_increment_iip(v); return IA64_NO_FAULT; } else if (iim == DOMN_SAL_REQUEST) { - sal_emul(v); - vcpu_increment_iip(v); + if (d->arch.is_sioemu) + sioemu_sal_assist(v); + else { + sal_emul(v); + vcpu_increment_iip(v); + } return IA64_NO_FAULT; } else if (d->arch.is_sioemu && iim == SIOEMU_HYPERPRIVOP_CALLBACK_RETURN) { diff --git a/xen/include/asm-ia64/sioemu.h b/xen/include/asm-ia64/sioemu.h index fefd13bcf3..55988dc1ae 100644 --- a/xen/include/asm-ia64/sioemu.h +++ b/xen/include/asm-ia64/sioemu.h @@ -26,5 +26,6 @@ extern void sioemu_deliver_event (void); extern void sioemu_callback_return (void); extern void sioemu_io_emulate (unsigned long padr, unsigned long data, unsigned long data1, unsigned long word); - +extern void sioemu_wakeup_vcpu (int vcpu_id); +extern void sioemu_sal_assist (struct vcpu *v); #endif /* __ASM_SIOEMU_H_ */ diff --git a/xen/include/public/arch-ia64/sioemu.h b/xen/include/public/arch-ia64/sioemu.h index c34d6ecd5f..a98af6a487 100644 --- a/xen/include/public/arch-ia64/sioemu.h +++ b/xen/include/public/arch-ia64/sioemu.h @@ -22,6 +22,9 @@ #ifndef __XEN_PUBLIC_IA64_SIOEMU_H__ #define __XEN_PUBLIC_IA64_SIOEMU_H__ +/* SIOEMU specific hypercalls. + The numbers are the minor part of FW_HYPERCALL_SIOEMU. */ + /* Defines the callback entry point. r8=ip, r9=data. Must be called per-vcpu. */ #define SIOEMU_HYPERCALL_SET_CALLBACK 0x01 @@ -35,6 +38,39 @@ /* Get wallclock time. */ #define SIOEMU_HYPERCALL_GET_TIME 0x04 +/* Get/Set shadow registers. */ +#define SIOEMU_HYPERCALL_GET_REGS 0x05 +#define SIOEMU_HYPERCALL_SET_REGS 0x06 + +/* Flush cache. */ +#define SIOEMU_HYPERCALL_FLUSH_CACHE 0x07 + +/* Get freq base. */ +#define SIOEMU_HYPERCALL_FREQ_BASE 0x08 + +/* Return from callback. */ +#define SIOEMU_HYPERCALL_CALLBACK_RETURN 0x09 + +/* Deliver an interrupt. */ +#define SIOEMU_HYPERCALL_DELIVER_INT 0x0a + +/* SIOEMU callback reason. */ + +/* An event (from event channel) has to be delivered. */ +#define SIOEMU_CB_EVENT 0x00 + +/* Emulate an IO access. */ +#define SIOEMU_CB_IO_EMULATE 0x01 + +/* An IPI is sent to a dead vcpu. */ +#define SIOEMU_CB_WAKEUP_VCPU 0x02 + +/* A SAL hypercall is executed. */ +#define SIOEMU_CB_SAL_ASSIST 0x03 + + +/* SIOEMU firmware mode hypercalls. */ + /* Return from callback. r16=0. Unmask vcpu events. */ #define SIOEMU_HYPERPRIVOP_CALLBACK_RETURN 0x01 -- 2.30.2